package com.cloudkinto.service.order.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.error.ErrorEnum;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.exception.BizExceptionI18;
import com.cloudkinto.common.exception.NotSufficientFundsException;
import com.cloudkinto.common.utils.*;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.finance.CompanyAccountService;
import com.cloudkinto.service.operate.OperateRecordService;
import com.cloudkinto.service.order.OrderTiktokService;

import com.cloudkinto.service.order.vo.tiktok.MarkPackageAsShippedReq;
import com.cloudkinto.service.order.vo.tiktok.OrderTiktokQueryBo;
import com.cloudkinto.service.order.vo.tiktok.OrderVO;
import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.OrderOutputAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputPackageAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputProductAddReq;
import com.cloudkinto.service.shipprice.ShipPriceService;
import com.cloudkinto.service.stock.StockRecordService;
import com.cloudkinto.service.stock.impl.StockRecordServiceImpl;
import com.cloudkinto.service.stock.vo.transfer.StockTransferAddReq;
import com.cloudkinto.service.stock.vo.transfer.StockTransferProductAdd;
import com.cloudkinto.service.user.UserService;
import com.cloudkinto.service.user.vo.AuthResponse;
import com.cloudkinto.utils.CustomApiClient;
import com.cloudkinto.utils.CustomFulfillmentV202309Api;
import com.cloudkinto.utils.CustomProductV202502Api;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import tiktokshop.open.sdk_java.api.AuthorizationV202309Api;
import tiktokshop.open.sdk_java.api.FulfillmentV202309Api;
import tiktokshop.open.sdk_java.api.LogisticsV202309Api;
import tiktokshop.open.sdk_java.api.OrderV202309Api;
import tiktokshop.open.sdk_java.invoke.ApiClient;
import tiktokshop.open.sdk_java.invoke.ApiException;
import tiktokshop.open.sdk_java.invoke.Configuration;
import tiktokshop.open.sdk_java.model.Authorization.V202309.GetAuthorizedShopsResponse;
import tiktokshop.open.sdk_java.model.Fulfillment.V202309.GetTrackingResponse;
import tiktokshop.open.sdk_java.model.Fulfillment.V202309.MarkPackageAsShippedRequestBody;
import tiktokshop.open.sdk_java.model.Fulfillment.V202309.MarkPackageAsShippedResponse;
import tiktokshop.open.sdk_java.model.Logistics.V202309.GetShippingProvidersResponse;
import tiktokshop.open.sdk_java.model.Logistics.V202309.GetShippingProvidersResponseDataShippingProviders;
import tiktokshop.open.sdk_java.model.Order.V202309.*;
import tiktokshop.open.sdk_java.model.Product.V202502.SearchProductsRequestBody;
import tiktokshop.open.sdk_java.model.Product.V202502.SearchProductsResponse;

import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.cloudkinto.common.constant.GlobalConstants.*;

@Service
public class OrderTiktokServiceImpl implements OrderTiktokService {

    private static final Logger log = LoggerFactory.getLogger(OrderTiktokServiceImpl.class);
    public static final int BATCH_SIZE = 500;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private TiktokOrderPackageDao tiktokOrderPackageDao;
    @Autowired
    private UserService userService;

    @Autowired
    private TiktokOrderPaymentDao tiktokOrderPaymentDao;

    /*@Autowired
    private TiktokOrderRecipientAddressDao tiktokOrderRecipientAddressDao;*/
    @Autowired
    private UserDao userDao;
    @Autowired
    private TiktokOrderDao tiktokOrderDao;
    @Autowired
    private TiktokOrderLineItemDao tiktokOrderLineItemDao;

    @Value("${tiktok.client.id}")
    private String clientId;

    @Value("${tiktok.client.secret}")
    private String clientSecret;

    @Value("${tiktok.redirect.uri}")
    private String redirectUri;

    @Value("${tiktok.client.app-key}")
    private String appKey;

    @Autowired
    private RedisTemplate redisTemplate;

    private final RestTemplate restTemplate = new RestTemplate();

    private static String accessToken = null;
    @Autowired
    private OperateRecordService operateRecordDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private StockRecordDao stockDao;
    @Autowired
    private ShipPriceService shipPriceService;
    @Autowired
    private ProductSkuMapDao productSkuMapDao;
    @Autowired
    private CompanyAccountService companyAccountService;
    @Autowired
    private OrderOutputService outputService;
    @Autowired
    private OrderTiktokService tiktokService;
    @Autowired
    private StockRecordService stockRecordService;


    // 初始化客户端

/*
    @Override
    public String generateAuthUrl() {
        return "https://auth.tiktok-shops.com/api/v2/authorize?" +
                "app_key=" + appKey +
                "&redirect_uri=" + redirectUri +
                "&response_type=code" +
                "&scope=seller.basic.read seller.order.read seller.payment.read seller.product.write seller.account.read";
    }*/



    @Override
    public String generateAuthUrl() {
        return "https://auth.tiktok-shops.com/api/v2/authorize?" +
                "app_key=" + appKey +
                "&response_type=code" +
                "&scope=seller.basic.read seller.order.read seller.payment.read seller.product.write seller.account.read";
    }

    @Override
    public SingleResult<AuthResponse> getAccessToken(String authCode) {
        String tokenUrl = "https://auth.tiktok-shops.com/api/v2/token/get?" +
                "app_key=" + appKey +
                "&app_secret=" + clientSecret +
                "&auth_code=" + authCode +
                "&grant_type=authorized_code";

        System.out.println("---------------------------test-----------------------");
        System.out.println(tokenUrl);
        System.out.println("-----------------------------------------------------");

        // 使用 RestTemplate 发起 GET 请求
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(tokenUrl, String.class);

        System.out.println("-----------------------------------------------------");
        System.out.println(responseEntity.getBody());
        if (responseEntity.getStatusCode().is2xxSuccessful()) {
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonNode = objectMapper.readTree(responseEntity.getBody());

                // 解析 data 字段为 AuthResponse 对象
                AuthResponse authResponse = objectMapper.treeToValue(jsonNode.get("data"), AuthResponse.class);
                accessToken = authResponse.getAccess_token();
                System.out.println("---------------------------------------------");
                System.out.println(authResponse);
                System.out.println("----------------------------------------------");
                // 返回成功的结果
                return SingleResult.success(authResponse);
            } catch (JsonProcessingException e) {
                // 处理 JSON 解析异常
                return SingleResult.failure("Failed to parse response: " + e.getMessage());
            }
        } else {
            // 请求失败时返回错误信息
            return SingleResult.failure("Failed to get access token, HTTP status: " + responseEntity.getStatusCodeValue());
        }
    }


    public SingleResult<AuthResponse> refreshAccessToken(String refreshToken,Long shopId) throws IOException {
        String accessTokenKey = TiktokAccessToken + shopId;
        String refreshTokenKey = TiktokRefreshToken + shopId;
        String accessTokenExpireKey = TiktokExpiresIn + shopId;
        String refreshTokenExpireKey =TiktokRefreshExpiresIn+shopId;

        String refreshTokenUrl = "https://auth.tiktok-shops.com/api/v2/token/refresh?" +
                "app_key=" + appKey +
                "&app_secret=" + clientSecret +
                "&refresh_token=" + refreshToken +
                "&grant_type=refresh_token";

        URL url = new URL(refreshTokenUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");

        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder response = new StringBuilder();
        String line;

        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        reader.close();

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(response.toString());
        AuthResponse authResponse = objectMapper.treeToValue(jsonNode.get("data"), AuthResponse.class);
        long currentTime = System.currentTimeMillis()/1000;
        // 设置 token 并添加过期时间,统一时间单位是秒(seconds)
        if(authResponse.getAccess_token()!=null) {
            redisTemplate.opsForValue().set(accessTokenKey, authResponse.getAccess_token());
            redisTemplate.expire(accessTokenKey, (authResponse.getAccess_token_expire_in() -currentTime ), TimeUnit.SECONDS);
        }else{
            log.error("TikTok token refresh failed, response: {}", response.toString());
            throw new BizExceptionI18("tiktok刷新token获取token出错!");
        }
        if(authResponse.getRefresh_token()!=null) {
            redisTemplate.opsForValue().set(refreshTokenKey, authResponse.getRefresh_token());
            redisTemplate.expire(refreshTokenKey, (authResponse.getRefresh_token_expire_in() - currentTime ), TimeUnit.SECONDS);
        }else{
            log.error("TikTok token refresh failed, response: {}", response.toString());
            throw new BizExceptionI18("tiktok刷新token获取refresh_token出错!");
        }
        if(authResponse.getAccess_token_expire_in()!=null){
        redisTemplate.opsForValue().set(accessTokenExpireKey, authResponse.getAccess_token_expire_in());
        redisTemplate.expire(accessTokenExpireKey, (authResponse.getAccess_token_expire_in() - currentTime), TimeUnit.SECONDS);
        }else {
            log.error("TikTok token refresh failed, response: {}", response.toString());
            throw new BizExceptionI18("tiktok刷新token获取access_token_expire_in出错!");
        }
        if(authResponse.getRefresh_token_expire_in()!=null) {
            redisTemplate.opsForValue().set(refreshTokenExpireKey, authResponse.getRefresh_token_expire_in());
            redisTemplate.expire(refreshTokenExpireKey, (authResponse.getRefresh_token_expire_in() - currentTime ), TimeUnit.SECONDS);
        }else {
            log.error("TikTok token refresh failed, response: {}", response.toString());
            throw new BizExceptionI18("tiktok刷新token获取refresh_token_expire_in出错!");
        }
        return SingleResult.success(authResponse);
    }



    @Override
    public SearchProductsResponse searchProducts(Integer shopId, int pageNumber, int pageSize) {

        CustomApiClient defaultClient = new CustomApiClient();
        defaultClient.setAppkey(appKey);
        defaultClient.setSecret(clientSecret);
        defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");

        CustomProductV202502Api apiInstance = new CustomProductV202502Api(defaultClient);
        SearchProductsRequestBody searchProductsRequestBody = new SearchProductsRequestBody();
        ShopDo shopDo = shopDao.selectById(shopId);
        String shopCipher = shopDo.getShopCipher();
        accessToken = shopDo.getTiktokAccessToken();
        SearchProductsResponse result = null;
        try {
            result = apiInstance.product202502ProductsSearchPost(100, accessToken,
                    "application/json", "", shopCipher, searchProductsRequestBody);
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
        System.out.println(result);
        return result;
    }




    @Override
    public GetAuthorizedShopsResponse authorizeShop(String accessToken) throws Exception {
        ApiClient defaultClient = Configuration.getDefaultApiClient()
                .setAppkey(appKey)
                .setSecret(clientSecret)
                .setBasePath("https://open-api.tiktokglobalshop.com");
        AuthorizationV202309Api apiInstance = new AuthorizationV202309Api(defaultClient);
        GetAuthorizedShopsResponse result = apiInstance.authorization202309ShopsGet(accessToken, "application/json");
        System.out.println(result);
        return result;
    }



    @Override
    public List<Map> shopListFromPlantForm(Long companyId) {

        List<Map> shopList = new ArrayList<>();
        // UserDo userDo = userDao.selectById(userId);
        //todo :待修改
     /*   if (userDo == null) {
            throw new BizException(SysConstant.User_NotExist);
        }*/
        QueryWrapper<ShopDo> shopWrapper = new QueryWrapper<>();
      /*  if (userDo.getShopId() != null)
            shopWrapper.eq("id", userDo.getShopId());*/
        shopWrapper.eq(companyId != null, "company_id", companyId);
        List<ShopDo> shopDoList = shopDao.selectList(shopWrapper);
        if (!CollectionUtils.isEmpty(shopDoList)) {
            for (ShopDo shopDo : shopDoList) {
                Map shopMap = new HashMap();
                shopMap.put("id", shopDo.getId());
                shopMap.put("value", shopDo.getShopName());
                shopMap.put("companyId", shopDo.getCompanyId());
                shopList.add(shopMap);
            }
        }
        return shopList;
    }

    @Override
    public PageResult getListPage(OrderTiktokQueryBo bo) {
        // 创建分页对象
        IPage<TiktokOrderDo> page = new Page<>(bo.getCurrent(), bo.getPageSize());

        // 使用 selectPage 进行分页查询
        IPage<TiktokOrderDo> orderPage = tiktokOrderDao.selectPage(page, queryBuild(bo));

        // 处理 VO 转换
        List<OrderVO> resList = handlerListAfter(orderPage.getRecords());

        // 构造并返回正确的分页结果
        return new PageResult(
                resList,
                (int) orderPage.getCurrent(),
                (int) orderPage.getSize(),
                (int) orderPage.getTotal(),
                (int) orderPage.getPages()
        );
    }


    @Override
    public OrderVO detail(String id) {
        TiktokOrderDo tiktokOrderDo = tiktokOrderDao.selectById(id);
        Long shopId = tiktokOrderDo.getShopId();
        ShopDo shopDo = shopDao.selectById(shopId);
        String shopCipher = shopDo.getShopCipher();
        String tiktokAccessToken = shopDo.getTiktokAccessToken();

        return handleData(tiktokOrderDo, shopCipher, tiktokAccessToken);
    }

    @Override
    public SingleResult sync(Long shopId, String startDate, String endDate, Long companyId) throws Exception {
        ShopDo shopDo = shopDao.selectById(shopId);
        if (shopDo == null) {
            throw new BizException(SysConstant.Shop_NotExist);
        }

        String accessTokenKey = TiktokAccessToken + shopId;
        String refreshTokenKey = TiktokRefreshToken + shopId;
        String accessTokenExpireKey = TiktokExpiresIn + shopId;
        String refreshTokenExpireKey = TiktokRefreshExpiresIn + shopId;
        String shopCipherKey = TiktokShopCipher + shopId;

        String tiktokAccessToken = (String) redisTemplate.opsForValue().get(accessTokenKey);
        String tiktokShopCipher = (String) redisTemplate.opsForValue().get(shopCipherKey);

        Long currentTimeMillis = System.currentTimeMillis();

        // 1. 获取 access_token如果为空刷新token将获取数据写入数据库和redis
        if (StringUtils.isBlank(tiktokAccessToken)) {
            String tiktokRefreshToken =(String) redisTemplate.opsForValue().get(refreshTokenKey);
            //2.如果refreshToken为空重新登录
            if (StringUtils.isBlank(tiktokRefreshToken)) {
                throw new BizExceptionI18("tiktok.access.token.not.exist,please reloadLogin!");
            }

            try {
                //3.刷新token
                SingleResult<AuthResponse> authResponseSingleResult = refreshAccessToken(tiktokRefreshToken, shopId);
                AuthResponse authResponse = authResponseSingleResult.getData();

                if (authResponse == null || StringUtils.isBlank(authResponse.getAccess_token())) {
                    throw new BizExceptionI18("tiktok.token.refresh.fail");
                }
               //更新redis
                tiktokAccessToken = (String)redisTemplate.opsForValue().get(accessTokenKey);
            } catch (Exception e) {
                log.error("Failed to refresh access token", e);
                throw new BizExceptionI18("tiktok.token.refresh.fail");
            }
        }

        // 2. 获取 shopCipher
        if (StringUtils.isBlank(tiktokShopCipher)) {
            try {
                GetAuthorizedShopsResponse response = userService.authorizeShop(shopId);
                if (response == null || CollectionUtils.isEmpty(response.getData().getShops())) {
                    throw new BizExceptionI18("tiktok.shop.cipher.not.found");
                }

                String cipher = (String) redisTemplate.opsForValue().get(shopCipherKey);

                tiktokShopCipher = cipher;
            } catch (Exception e) {
                log.error("Failed to get shop cipher", e);
                throw new BizExceptionI18("tiktok.shop.cipher.not.found");
            }
        }

        log.info("获取订单信息 - accessToken: {}, shopCipher: {}", tiktokAccessToken, tiktokShopCipher);

        // 3. 同步订单
        try {
            getOrder(tiktokAccessToken, tiktokShopCipher, shopId, startDate, endDate, companyId);
        } catch (Exception e) {
            log.error("Failed to get orders", e);
            throw new BizExceptionI18("tiktok.order.sync.fail");
        }

        return SingleResult.success();
    }

   /* private String handleRedis(AuthResponse authResponse,  String accessTokenKey, String refreshTokenKey, String accessTokenExpireKey,String refreshTokenExpireKey, Long currentTimeMillis) {
        String tiktokAccessToken;
        String newAccessToken = authResponse.getAccess_token();
        String newRefreshToken = authResponse.getRefresh_token();
        Long accessTokenExpireIn = authResponse.getAccess_token_expire_in();
        Long refreshTokenExpireIn = authResponse.getRefresh_token_expire_in();
        // 更新 Redis - 设置值
        redisTemplate.opsForValue().set(accessTokenKey, newAccessToken);
        redisTemplate.opsForValue().set(refreshTokenKey, newRefreshToken);
        redisTemplate.opsForValue().set(accessTokenExpireKey, accessTokenExpireIn);
        redisTemplate.opsForValue().set(refreshTokenExpireKey, refreshTokenExpireIn);

        Long expireTime = accessTokenExpireIn - currentTimeMillis / 1000; // 转换为秒单位
        Long refreshExpireTime = refreshTokenExpireIn - currentTimeMillis / 1000;
        redisTemplate.expire(accessTokenKey, accessTokenExpireIn - currentTimeMillis / 1000, TimeUnit.SECONDS);
        redisTemplate.expire(refreshTokenKey, refreshTokenExpireIn - currentTimeMillis / 1000, TimeUnit.SECONDS);
        redisTemplate.expire(accessTokenExpireKey, expireTime, TimeUnit.SECONDS);
        redisTemplate.expire(refreshTokenExpireKey, refreshExpireTime, TimeUnit.SECONDS);
        tiktokAccessToken = newAccessToken;
        return tiktokAccessToken;
    }
*/

    @Override
    public SingleResult markSendOut(List<String> orderIds, Long userId) {
        if (orderIds == null || orderIds.size() == 0) {
            return SingleResult.failure("无数据");
        }

        for (String orderId : orderIds) {
            TiktokOrderDo tiktokOrderDo = tiktokOrderDao.selectOne(new LambdaQueryWrapper<TiktokOrderDo>().eq(TiktokOrderDo::getOrderId, orderId));
            if (tiktokOrderDo.getIsSendOut() == null) {
                tiktokOrderDo.setIsSendOut(1);
                tiktokOrderDao.updateById(tiktokOrderDo);
                //TODO 类型未知 假设类型为100
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_MARK_SEND, tiktokOrderDo.getId(), userId, 100);
            }
        }

        return SingleResult.success();
    }


    @Override
    public SingleResult sendOut(String[] ids, Long userId, Long companyId, boolean isAuto) {
//        sufficientFundsCheck(companyId);
        List<OrderOutputAddReq> orderOutputAddReqList = new ArrayList<>();
        List<String> failOrders = new ArrayList<>();
        if (ids == null || ids.length < 1) {
            return SingleResult.failure("无数据");
        }
        List<TiktokOrderDo> tiktokOrderDos = tiktokOrderDao.selectBatchIds(Arrays.asList(ids));
        for (TiktokOrderDo tiktokOrderDo : tiktokOrderDos) {
            if ("Canceled".equals(tiktokOrderDo.getStatus()) || "refunded".equals(tiktokOrderDo.getStatus()) || "voided".equals(tiktokOrderDo.getStatus())) {
                failOrders.add(StringsUtil.createI18Message("该订单已废弃") + tiktokOrderDo.getId());
                continue;
            }
            // if (!tiktokOrderDo.getFulfillmentStatus().equals("unshipped") && isAuto) {
            //     failOrders.add(StringsUtil.createI18Message("该订单不处于待发货状态") + tiktokOrderDo.getOrderName());
            //     continue;
            // }
            OrderOutputAddReq res = new OrderOutputAddReq();
            LambdaQueryWrapper<TiktokOrderLineItemDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TiktokOrderLineItemDo::getOrderId, tiktokOrderDo.getOrderId());
            List<TiktokOrderLineItemDo> itemsDoList = tiktokOrderLineItemDao.selectList(wrapper);

            //订单
//            res.setOrderType(1);
//        res.setStatus(0);
            res.setSendDate(new Date());
            res.setPlatform("tiktok");
            res.setPlatformNumber(tiktokOrderDo.getId() + "");
            // res.setPlatformNumber(tiktokOrderDo.getOrderId() + "");
            res.setShopId(tiktokOrderDo.getShopId().longValue());
            res.setCompanyId(tiktokOrderDo.getCompanyId());
            res.setOrderNo(tiktokOrderDo.getOrderId());
            res.setReceiverName(tiktokOrderDo.getLastName() + tiktokOrderDo.getFirstName());
            res.setTelPhone(tiktokOrderDo.getPhoneNumber());
            res.setPostCode(tiktokOrderDo.getPostalCode());
            res.setArea(tiktokOrderDo.getRegionCode());
            // if (org.apache.commons.lang.StringUtils.isNotBlank(tiktokOrderDo.get())) {
            //     res.setAddress(tiktokOrderDo.getShippingCity() + tiktokOrderDo.getShippingAddress());
            // } else {
            StringBuilder addressSB= new StringBuilder();
            if (StringUtils.isNotBlank(tiktokOrderDo.getDistrictInfoAddressName1()))
            addressSB.append(tiktokOrderDo.getDistrictInfoAddressName1());
            if (StringUtils.isNotBlank(tiktokOrderDo.getDistrictInfoAddressName2()))
            addressSB.append(tiktokOrderDo.getDistrictInfoAddressName2());
            if (StringUtils.isNotBlank(tiktokOrderDo.getDistrictInfoAddressName3()))
            addressSB.append(tiktokOrderDo.getDistrictInfoAddressName3());
            if (StringUtils.isNotBlank(tiktokOrderDo.getDistrictInfoAddressName4()))
                addressSB.append(tiktokOrderDo.getDistrictInfoAddressName4());
            addressSB.append(tiktokOrderDo.getAddressDetail());
            res.setAddress(addressSB.toString());
            // }
            if (tiktokOrderDo.getDeliveryOptionRequiredDeliveryTime() != null) {
                res.setDeliveryDate(TimeUtils.formatDate(tiktokOrderDo.getDeliveryOptionRequiredDeliveryTime()));
                // int time1 = Integer.parseInt(TimeUtils.formatDate(tiktokOrderDo.getEarliestDeliveryDate(), "HH")) + 1;
                // String startTime = time1 < 10 ? "0" + time1 : String.valueOf(time1);
                // int time2 = Integer.parseInt(TimeUtils.formatDate(tiktokOrderDo.getLastDeliveryDate(), "HH")) + 1;
                // String endTime = time2 < 10 ? "0" + time2 : String.valueOf(time2);
                // res.setDeliveryTime(startTime +
                //         "-" + endTime);
            }
            long storageId = 0L;
            long stateId = 0;
            //item
            List<OrderOutputProductAddReq> orderOutputProductDetailList = new ArrayList<>();
            List<TiktokOrderLineItemDo> failedItems = new ArrayList<>();
            if (!CollectionUtils.isEmpty(itemsDoList)) {
                double[] size = new double[4];
                double shipPirce = 99999D;
                //默认仓库先捆包
                for (TiktokOrderLineItemDo itemsDo : itemsDoList) {
                    Long productId = getProductId(itemsDo.getSellerSku(), tiktokOrderDo.getCompanyId());
                    if (productId == null) {
                        failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, tiktokOrderDo.getId(), itemsDo.getSellerSku()));
                        continue;
                    }
                    //东京仓库优先发货仓库
                    storageId = 15L;

                    // LambdaQueryWrapper<StockRecordDo> wrapper1 = new LambdaQueryWrapper<>();
                    // wrapper1.eq(StockRecordDo::getShopId, res.getShopId())
                    //         .eq(StockRecordDo::getProductInfoId, productId)
                    //         .eq(StockRecordDo::getStorageId, storageId);
                    // StockRecordDo stockRecordDo = stockDao.selectOne(wrapper1);
                    // if (stockRecordDo == null) {
                    //     failedItems.add(itemsDo);
                    //     continue;
                    // }
                    // int noDeliveredCount = stockDao.getOrderOutCount(productId, res.getShopId(), storageId) +
                    //         stockDao.getOrderOutTurn2FbaCount(productId, res.getShopId(), storageId);
                    int count = itemsDo.getSkuCount();
                    if (count < 1) {
                        count = itemsDo.getSkuCount();
                    }
                    int canUseCount = stockRecordService.getStockCount(res.getCompanyId(), res.getShopId(), storageId, productId, count);

                    if (canUseCount < count) {
                        //优先仓库有库存，优先仓库发货
                        failedItems.add(itemsDo);
                        continue;
                    }
                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                    // productDetail.setOrderId(itemsDo.getOrderId());
                    productDetail.setProductId(productId);
                    productDetail.setCount(count);
                    orderOutputProductDetailList.add(productDetail);
                }


                OrderOutputPackageAddReq packageDetail = new OrderOutputPackageAddReq();
                List<OrderOutputPackageAddReq> packageAddReqList = new ArrayList<>();
                packageDetail.setProductList(orderOutputProductDetailList);
                OrderOutputAddReq addReq = new OrderOutputAddReq();
                BeanUtils.copyProperties(res, addReq);
                packageAddReqList.add(packageDetail);
                addReq.setStorageId(storageId);
                addReq.setPackageList(packageAddReqList);
                //默认仓库库存不足
                if (failedItems.size() != itemsDoList.size() && storageId != 0) {
                    orderOutputAddReqList.add(addReq);
                } //一个仓库是否发完所有订单
                if (failedItems.size() > 0) {
                    List<OrderOutputProductAddReq> productAddList = new ArrayList<>();
                    //剩余一件商品无库存
                    if (failedItems.size() == 1 && failedItems.get(0).getSkuCount() == 1) {
                        storageId = 0L;
                        Long productId = getProductId(failedItems.get(0).getSellerSku(), res.getCompanyId());
                        List<StorageDo> storageDos = storageDao.selectList(null);
                        int count = failedItems.get(0).getSkuCount();
                      /*  if (count < 1) {
                            count = failedItems.get(0).getSkuCount();
                        }*/
                        for (StorageDo storageDo : storageDos) {
                            //遍历仓库是否都有库存
                            // LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper();
                            // wrapper2.eq(StockRecordDo::getShopId, res.getShopId())
                            //         .eq(StockRecordDo::getProductInfoId, productId)
                            //         .eq(StockRecordDo::getStorageId, storageDo.getId());
                            // StockRecordDo stockRecordDo1 = stockDao.selectOne(wrapper2);
                            // size = shipPriceService.countSameSkuSize(new double[4], productId, count);
                            // int noDeliveredCount1 = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId())
                            //         + stockDao.getOrderOutTurn2FbaCount(productId, res.getShopId(), storageDo.getId());
                            //
                            // int count = itemsDo.getCount();
                            int canUseCount = stockRecordService.getStockCount(res.getCompanyId(), res.getShopId(), storageId, productId, count);
                            if (canUseCount >= count) {
                                List<ShipPriceDo> shipPriceDos = shipPriceService.queryByRegionAndSize(res.getPostCode(), size, res.getCod(), res.getShipmentType(), storageDo.getId(), 1, res.getCompanyId());
                                if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0) {
                                    continue;
                                }
                                if (shipPirce > shipPriceDos.get(0).getPrice()) {
                                    //选择最便宜的价格
                                    shipPirce = shipPriceDos.get(0).getPrice();
                                    storageId = storageDo.getId();
                                }
                            }
                        }
                        OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                        productDetail.setProductId(productId);
                        productDetail.setCount(count);
                        productAddList.add(productDetail);
                        OrderOutputPackageAddReq packageDetail1 = new OrderOutputPackageAddReq();
                        if (storageId != 0) {
                            List<OrderOutputPackageAddReq> packageAddReqList1 = new ArrayList<>();
                            packageDetail1.setProductList(productAddList);
                            OrderOutputAddReq addReq1 = new OrderOutputAddReq();
                            BeanUtils.copyProperties(res, addReq1);
                            packageAddReqList1.add(packageDetail1);
                            addReq1.setStorageId(storageId);
                            addReq1.setPackageList(packageAddReqList1);
//                            if (orderCount > 0) addReq.setOrderNo(addReq.getOrderNo() + "-" + orderCount);
//                            orderCount++;
                            orderOutputAddReqList.add(addReq1);
                        } else {
                            failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Stock_NotEnough, tiktokOrderDo.getId(),
                                    failedItems.get(0).getCombinedListingSkusSellerSku()));
                        }
                    } else {
                        List<OrderOutputProductAddReq> productAddList1 = new ArrayList<>();
                        //多件商品无库存，第二优先捆包
                        List<TiktokOrderLineItemDo> productDoListFailed = new ArrayList<>();
                        List<TiktokOrderLineItemDo> productDoListSuccess = new ArrayList<>();
                        LambdaQueryWrapper<StorageDo> lambdaQueryWrapper = new LambdaQueryWrapper();
                        lambdaQueryWrapper.eq(StorageDo::getSupportShip, 1).ne(StorageDo::getId, storageId);
                        if (stateId <= 7) {
                            lambdaQueryWrapper.orderByDesc(StorageDo::getStorageArea);
                        } else {
                            lambdaQueryWrapper.orderByAsc(StorageDo::getStorageArea);
                        }
                        List<StorageDo> storageDos = storageDao.selectList(lambdaQueryWrapper);
                        storageId = 0L;
                        if (storageDos != null) {
                            kk:
                            for (StorageDo storageDo : storageDos) {
                                ;//遍历支持捆包仓库是否都有库存
                                for (TiktokOrderLineItemDo productDo : failedItems) {
                                    Long productId = getProductId(productDo.getCombinedListingSkusSellerSku(), res.getCompanyId());
                                    int count = productDo.getSkuCount();
                                    if (count < 1) {
                                        count = productDo.getSkuCount();
                                    }
                                    // LambdaQueryWrapper<StockRecordDo> wrapper1 = new LambdaQueryWrapper<>();
                                    // wrapper1.eq(StockRecordDo::getShopId, res.getShopId())
                                    //         .eq(StockRecordDo::getProductInfoId, productId)
                                    //         .eq(StockRecordDo::getStorageId, storageDo.getId());
                                    // StockRecordDo stockRecordDo = stockDao.selectOne(wrapper1);
                                    // if (stockRecordDo == null) {
                                    //     productDoListSuccess.clear();
                                    //     productDoListFailed.clear();
                                    //     productDoListFailed.addAll(failedItems);
                                    //     continue kk;
                                    // }
                                    // int noDeliveredCount = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId()) + stockDao.getOrderOutTurn2FbaCount(productId, res.getShopId(), storageDo.getId());
                                    int canUseCount = stockRecordService.getStockCount(res.getCompanyId(), res.getShopId(), storageId, productId, count);
                                    if (canUseCount < count) {
                                        productDoListSuccess.clear();
                                        productDoListFailed.clear();
                                        productDoListFailed.addAll(failedItems);
                                        continue kk;
                                    } else {
                                        productDoListSuccess.add(productDo);
                                    }
                                    storageId = storageDo.getId();
                                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                                    productDetail.setProductId(productId);
                                    productDetail.setCount(count);
                                    productAddList1.add(productDetail);
                                }
                                if (productDoListSuccess.size() == failedItems.size()) {
                                    productDoListSuccess.clear();
                                    productDoListFailed.clear();
                                    packageDetail = new OrderOutputPackageAddReq();
                                    List<OrderOutputPackageAddReq> packageAddReqList1 = new ArrayList<>();
                                    packageDetail.setProductList(productAddList1);
                                    OrderOutputAddReq addReq1 = new OrderOutputAddReq();
                                    BeanUtils.copyProperties(res, addReq1);
                                    packageAddReqList1.add(packageDetail);
                                    if (storageId != 0) {
                                        addReq1.setStorageId(storageId);
                                        addReq1.setPackageList(packageAddReqList1);
                                        orderOutputAddReqList.add(addReq1);
                                        break kk;
                                    }
                                } else {
                                    productDoListSuccess.clear();
                                    productDoListFailed.addAll(failedItems);
                                    continue kk;
                                }
                            }
                        } else {
                            productDoListFailed.addAll(failedItems);
                        }
                        List<OrderOutputProductAddReq> productAddList2;
                        //所有捆包仓库无库存的产品
                        if (productDoListFailed.size() > 0) {//捆包仓库无库存，分别发
                            LambdaQueryWrapper<StorageDo> queryWrapper = new LambdaQueryWrapper<>();
                            queryWrapper.eq(StorageDo::getCountryType, 1);
                            List<StorageDo> storageDoList = storageDao.selectList(queryWrapper);
                            for (TiktokOrderLineItemDo productDo : productDoListFailed) {
                                storageId = 0L;
                                shipPirce = 99999D;
                                Long productId = getProductId(productDo.getCombinedListingSkusSellerSku(), res.getCompanyId());
                                int count = productDo.getSkuCount();
                                if (count < 1) {
                                    count = productDo.getSkuCount();
                                }
                                for (StorageDo storageDo : storageDoList) {
                                    //遍历仓库是否都有库存
                                    LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper<>();
                                    size = shipPriceService.countSameSkuSize(new double[4], productId, 1);
                                    // wrapper2.eq(StockRecordDo::getShopId, res.getShopId()).eq(StockRecordDo::getProductInfoId, productId).eq(StockRecordDo::getStorageId, storageDo.getId());
                                    // StockRecordDo stockRecordDo1 = stockDao.selectOne(wrapper2);
                                    // int noDeliveredCount1 = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId()) + stockDao.getOrderOutTurn2FbaCount(productId, res.getShopId(), storageDo.getId());
                                    int canUseCount = stockRecordService.getStockCount(res.getCompanyId(), res.getShopId(), storageId, productId, count);

                                    if (canUseCount >= count) {
                                        List<ShipPriceDo> shipPriceDos = shipPriceService.queryByRegionAndSize(res.getPostCode(), size, res.getCod(), res.getShipmentType(), storageDo.getId(), 1, res.getCompanyId());
                                        if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0) {
                                            continue;
                                        }
                                        if (shipPirce > shipPriceDos.get(0).getPrice()) {
                                            //选择最便宜的价格
                                            shipPirce = shipPriceDos.get(0).getPrice();
                                            storageId = storageDo.getId();
                                        }
                                    }
                                }
                                if (storageId != 0) {
                                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                                    productAddList2 = new ArrayList<>();
                                    productDetail.setProductId(productId);
                                    productDetail.setCount(count);
                                    productAddList2.add(productDetail);
                                    packageDetail = new OrderOutputPackageAddReq();
                                    packageAddReqList = new ArrayList<>();
                                    packageDetail.setProductList(productAddList2);
                                    addReq = new OrderOutputAddReq();
                                    BeanUtils.copyProperties(res, addReq);
                                    packageAddReqList.add(packageDetail);
                                    addReq.setStorageId(storageId);
                                    addReq.setPackageList(packageAddReqList);
//                                if (orderCount > 0) addReq.setOrderNo(addReq.getOrderNo() + "-" + orderCount);
//                                orderCount++;
                                    orderOutputAddReqList.add(addReq);
                                } else {
                                    //剩余SKU都没有库存
                                    failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Stock_NotEnough, tiktokOrderDo.getId(),
                                            failedItems.get(0).getCombinedListingSkusSellerSku()));
                                }
                            }
                        }
                    }
                }
            }
            if (orderOutputAddReqList.size() > 0) {
                // operateRecordDao.operateAddRecord(SysConstant.OPERATE_CLICK_SEND, tiktokOrderDo.getId() + "", userId, 7);
            }
        }
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            StringBuilder sku = new StringBuilder();
            int cout = 0;
            for (OrderOutputProductAddReq orderOutputProductAddReq : outputAddReq.getPackageList().get(0).getProductList()) {
                cout = cout + orderOutputProductAddReq.getCount();
                if (org.apache.commons.lang.StringUtils.isNotBlank(sku.toString())) {
                    sku.append(",");
                }
                sku.append(productInfoDao.selectById(orderOutputProductAddReq.getProductId()).getCommoditySku());
            }
            outputAddReq.setSku(sku.toString());
            outputAddReq.setCount(cout);
        }
        if (isAuto) {
            sendOutMatch(orderOutputAddReqList, userId, isAuto);
        }

        Map<String, Object> map = new HashMap<>(8);
        map.put("orderList", orderOutputAddReqList);
        map.put("failedList", failOrders);
        map.put("storageList", storageDao.selectList(null));
        return SingleResult.success(map);
    }

    @Override
    public SingleResult sendOutMatch(List<OrderOutputAddReq> orderOutputAddReqList, Long userId, boolean isAuto) {
        List<String> failOrders = new ArrayList<>();
        failOrders.addAll(outputService.addTiktokList(orderOutputAddReqList, userId));
//        return SingleResult.success(String.format("成功导出%d个发货单", orderOutputAddReqList.size() - failOrders.size()), failOrders);;
        if (failOrders.size() > 0) {
            return SingleResult.failure("300", SysConstant.OrderYahoo_Export_Success, failOrders, orderOutputAddReqList.size() - failOrders.size());
        } else {
            return SingleResult.success(failOrders);
        }
    }

    private void sufficientFundsCheck(Long companyId) {
        if (!companyAccountService.getIsDue(companyId)) {
            throw new NotSufficientFundsException(ErrorEnum.NOT_SUFFICIENT_FUNDS);
        }
    }

    private Long getProductId(String sellerSku, Long companyId) {
        QueryWrapper productWrapper = new QueryWrapper();
        productWrapper.eq("commodity_sku", sellerSku);
        productWrapper.eq("company_id", companyId);
        productWrapper.last("limit 1");
        ProductInfoDo productInfoDo = productInfoDao.selectOne(productWrapper);
        if (productInfoDo == null) {
            QueryWrapper skuWrapper = new QueryWrapper();
            skuWrapper.eq("sub_sku", sellerSku);
            skuWrapper.eq("company_id", companyId);
            skuWrapper.last("limit 1");
            ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
            if (productSkuMapDo == null) {
                return null;
            }
            return productSkuMapDo.getProductInfoId();
        } else {
            return productInfoDo.getId();
        }
    }




    @Override
    public String markPackageAsShipped(List<Map<String, List<OrderOutputPackageDetailDo>>> orderRequests) {

        for (Map<String, List<OrderOutputPackageDetailDo>> order : orderRequests) {
            for (String orderId : order.keySet()) {
                MarkPackageAsShippedReq req = new MarkPackageAsShippedReq();
                List<TiktokOrderDo> tiktokOrderDos = tiktokOrderDao.selectList(new LambdaQueryWrapper<TiktokOrderDo>().eq(TiktokOrderDo::getOrderId, orderId));

                TiktokOrderDo tiktokOrderDo = tiktokOrderDos.get(0);
                req.setShopId(tiktokOrderDo.getShopId());
                //todo
                List<OrderOutputPackageDetailDo> packageDetailDos = order.get(orderId);

                List<TiktokOrderLineItemDo> tiktokOrderLineItemDos = tiktokOrderLineItemDao.selectList(new LambdaQueryWrapper<TiktokOrderLineItemDo>()
                        .eq(TiktokOrderLineItemDo::getOrderId, orderId));
                List<String> lineItemIds = tiktokOrderLineItemDos.stream().map(tiktokOrderLineItemDo -> tiktokOrderLineItemDo.getId()).collect(Collectors.toList());
                req.setOrderLineItemIds(lineItemIds);

                ShopDo shopDo = shopDao.selectById(req.getShopId());
                if (shopDo == null) {
                    throw new BizException(SysConstant.Shop_NotExist);
                }
                // 1. 获取 shop_cipher 和 app_key
                String shopCipher = shopDo.getShopCipher();
                String tiktokAccessToken = shopDo.getTiktokAccessToken();
                String shippingProviderId = getShippingProviders(tiktokOrderDo.getDeliveryOptionId(), tiktokAccessToken, shopCipher);

                // 2. 初始化 ApiClient
                CustomApiClient defaultClient = new CustomApiClient();
                defaultClient.setAppkey(appKey);
                defaultClient.setSecret(clientSecret);
                defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");

                // 3. 创建 API 实例
                CustomFulfillmentV202309Api apiInstance = new CustomFulfillmentV202309Api(defaultClient);

                // 4. 构建请求体
                MarkPackageAsShippedRequestBody requestBody = new MarkPackageAsShippedRequestBody();
                requestBody.setOrderLineItemIds(req.getOrderLineItemIds());
                //todo：trackingNumber暂时固定
                requestBody.setTrackingNumber("5366425868452693");
                requestBody.setShippingProviderId(shippingProviderId);


                // 5. 调用 API
                try {
                    MarkPackageAsShippedResponse result = apiInstance
                            .fulfillment202309OrdersOrderIdPackagesPost(orderId, tiktokAccessToken, "application/json", shopCipher, requestBody);
                    System.out.println("---------------------------------");
                    System.out.println(result);
                    System.out.println("---------------------------------");
                    if (result.getCode() == 0) {
                        tiktokOrderDo.setStatus("AWAITING_COLLECTION");
                        tiktokOrderDao.updateById(tiktokOrderDo);
                    }
                } catch (ApiException e) {
                    // 处理异常
                    e.printStackTrace();
                    return e.getMessage();

                }

            }

        }
        return "success";
    }



    @Override
    public String getShippingProviders(String deliveryOptionId, String tiktokAccessToken, String shopCipher) {
        try {
          /*  // 获取店铺信息
            ShopDo shopDo = shopDao.selectById(shopId);
            if (shopDo == null) {
                throw new RuntimeException("店铺不存在");
            }

            String shopCipher = shopDo.getShopCipher();
            String tiktokAccessToken = shopDo.getTiktokAccessToken();*/
            CustomApiClient defaultClient = new CustomApiClient();
            defaultClient.setAppkey(appKey);
            defaultClient.setSecret(clientSecret);
            defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");
            LogisticsV202309Api apiInstance = new LogisticsV202309Api(defaultClient);
            GetShippingProvidersResponse result = apiInstance.logistics202309DeliveryOptionsDeliveryOptionIdShippingProvidersGet(deliveryOptionId, tiktokAccessToken, "application/json", shopCipher);
            System.out.println(result);
            List<GetShippingProvidersResponseDataShippingProviders> shippingProviders = result.getData().getShippingProviders();
            String shippingProviderId = shippingProviders.get(0).getId();
            return shippingProviderId;
        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
    }

    @Override
    public GetTrackingResponse getTrackingInfo(String orderId) {
        List<TiktokOrderDo> tiktokOrderDos = tiktokOrderDao.selectList(new LambdaQueryWrapper<TiktokOrderDo>().eq(TiktokOrderDo::getId, orderId));
        GetTrackingResponse result = null;
        if (!tiktokOrderDos.isEmpty()) {
            TiktokOrderDo tiktokOrderDo = tiktokOrderDos.get(0);
            Long  shopId = tiktokOrderDo.getShopId();
            ShopDo shopDo = shopDao.selectById(shopId);
            String tiktokAccessToken = shopDo.getTiktokAccessToken();
            String shopCipher = shopDo.getShopCipher();
            CustomApiClient defaultClient = new CustomApiClient();
            defaultClient.setAppkey(appKey);
            defaultClient.setSecret(clientSecret);
            defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");
            FulfillmentV202309Api apiInstance = new FulfillmentV202309Api(defaultClient);

            try {
                result = apiInstance.fulfillment202309OrdersOrderIdTrackingGet(orderId, tiktokAccessToken, "application/json", shopCipher);
            } catch (ApiException e) {
                throw new RuntimeException(e);
            }
            System.out.println(result);
        }
        return result;
    }

    @Override
    public GetOrderDetailResponse detailOrder(String orderId) {
        // 2. 初始化 ApiClient
        CustomApiClient defaultClient = new CustomApiClient();
        TiktokOrderDo tiktokOrderDo = tiktokOrderDao.selectOne(new LambdaQueryWrapper<TiktokOrderDo>().eq(TiktokOrderDo::getOrderId, orderId));
        Long shopId = tiktokOrderDo.getShopId();
        ShopDo shopDo = shopDao.selectById(shopId);
        String tiktokAccessToken = shopDo.getTiktokAccessToken();
        String shopCipher = shopDo.getShopCipher();

        defaultClient.setAppkey(appKey);
        defaultClient.setSecret(clientSecret);
        defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");
        OrderV202309Api apiInstance = new OrderV202309Api(defaultClient);
        List<String> orders = new ArrayList<>();
        orders.add(orderId);
        GetOrderDetailResponse result = null;
        try {
            result = apiInstance.order202309OrdersGet(orders, tiktokAccessToken, "application/json", shopCipher);
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
        System.out.println(result);
        return result;
    }

    @Override
    public List<String> getOrderIds(List<Long> ids) {
        List<String> orderIds = tiktokOrderDao.selectList(new LambdaQueryWrapper<TiktokOrderDo>().in(TiktokOrderDo::getId, ids)).stream().map(TiktokOrderDo::getOrderId).collect(Collectors.toList());
        return orderIds;


    }

    @Override
    public void fixedTokenRefresh() {

        Object shopIdObj = redisTemplate.opsForValue().get(TiktokShopId);
        if (shopIdObj == null) {
            throw new BizExceptionI18("店铺ID不存在，请重新授权");
        }
        Long shopId = ((Number) shopIdObj).longValue();
        refreshTokenForSingleShop(shopId);

    }
    private void refreshTokenForSingleShop(Long shopId) {
        String refreshTokenKey = TiktokRefreshToken+shopId;
        String accessTokenExpireKey = TiktokExpiresIn+shopId;
        Long currentTime = System.currentTimeMillis()/1000;
        //判断是否需要通过refreshToken刷新token
        Object tokenExpireIn = redisTemplate.opsForValue().get(accessTokenExpireKey);
        Long accessTokenExpireIn = ((Number) tokenExpireIn).longValue();
    //    Long accessTokenExpireIn = 1751612113L;
        boolean  isTokenExpired = accessTokenExpireIn == null || currentTime+25*60*60 > accessTokenExpireIn;
        if(!isTokenExpired)
        {
            return;
        }

        String refreshToken = (String) redisTemplate.opsForValue().get(refreshTokenKey);
        if(refreshToken == null)
        {
            throw new BizExceptionI18("refreshToken不存在，请重新授权");
        }
       try{
           refreshAccessToken(refreshToken,shopId);
       } catch (IOException e) {
           throw new RuntimeException(e);
       }


    }


    private OrderVO handleData(TiktokOrderDo tiktokOrderDo, String shopCipher, String tiktokAccessToken) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(tiktokOrderDo, orderVO);
        String id = tiktokOrderDo.getOrderId();
        List<TiktokOrderPackageDo> tiktokOrderPackageDos = tiktokOrderPackageDao.selectList(new QueryWrapper<TiktokOrderPackageDo>().eq("order_id", id));
        List<String> packageIds = tiktokOrderPackageDos.stream().map(TiktokOrderPackageDo::getPackageId).collect(Collectors.toList());


        //获取包裹详情
        CustomApiClient defaultClient = new CustomApiClient();
        defaultClient.setAppkey(appKey);
        defaultClient.setSecret(clientSecret);
        defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");
        FulfillmentV202309Api apiInstance = new FulfillmentV202309Api(defaultClient);
        List<TiktokOrderPackageDo> packageDoList = new ArrayList<>();
       /* for (String packageId : packageIds) {
            try {
                GetPackageDetailResponse result = apiInstance.fulfillment202309PackagesPackageIdGet(packageId, tiktokAccessToken, "application/json", shopCipher);
                System.out.println("-----------package---------------");
                System.out.println(result);
                String packageStatus = result.getData().getPackageStatus();
                GetPackageDetailResponseData data = result.getData();

                TiktokOrderPackageVo packageVo = new TiktokOrderPackageVo();
                packageVo.setOrderId(id);
                packageVo.setPackageStatus(packageStatus);
                packageVo.setPackageId(packageId);
                packageVos.add(packageVo);
                System.out.println("----------------------------------");
                System.out.println(result);
            } catch (ApiException e) {
                throw new RuntimeException(e);
            }
        }*/

        TiktokOrderPaymentDo tiktokOrderPaymentDo = tiktokOrderPaymentDao.selectById(id);
        orderVO.setPayment(tiktokOrderPaymentDo);
        List<TiktokOrderLineItemDo> tiktokOrderLineItemDos = tiktokOrderLineItemDao.selectList(new QueryWrapper<TiktokOrderLineItemDo>().eq("order_id", id));
        orderVO.setItems(tiktokOrderLineItemDos);
        // TiktokOrderRecipientAddressDo tiktokOrderRecipientAddressDo = tiktokOrderRecipientAddressDao.selectById(id);
        //orderVO.setRecipientAddress(tiktokOrderRecipientAddressDo);

        orderVO.setPackages(tiktokOrderPackageDos);
        System.out.println("--------------------");
        System.out.println(orderVO);
        System.out.println("--------------------");
        return orderVO;
    }

    private List<OrderVO> handlerListAfter(List<TiktokOrderDo> tiktokOrderDos) {
        List<OrderVO> resList = new ArrayList<>();
        for (TiktokOrderDo tiktokOrderDo : tiktokOrderDos) {
            String id = tiktokOrderDo.getOrderId();
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(tiktokOrderDo, orderVO);
            orderVO.setOrderId(id);

            // 使用统一方法处理时间字段
            orderVO.setUpdateTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getUpdateTime()));
            orderVO.setTtsSlaTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getTtsSlaTime()));
            orderVO.setShippingDueTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getShippingDueTime()));
            orderVO.setRtsSlaTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getRtsSlaTime()));
            orderVO.setCancelOrderSlaTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getCancelOrderSlaTime()));
            orderVO.setCreateTime(TimeConvertUtils.formatTimestamp(tiktokOrderDo.getCreateTime()));


            // 查询订单包裹和商品项
            List<TiktokOrderPackageDo> packageList = tiktokOrderPackageDao.selectList(
                    new LambdaQueryWrapper<TiktokOrderPackageDo>().eq(TiktokOrderPackageDo::getOrderId, id));
            // 转换实体
            //  List<TiktokOrderPackageVo> packageVos = BeanCopierUtils.listCopyMapper(packageList, TiktokOrderPackageDo.class, TiktokOrderPackageVo.class);
            orderVO.setPackages(packageList);

            List<TiktokOrderLineItemDo> lineItems = tiktokOrderLineItemDao.selectList(
                    new LambdaQueryWrapper<TiktokOrderLineItemDo>().eq(TiktokOrderLineItemDo::getOrderId, id));
            orderVO.setItems(lineItems);

            List<TiktokOrderPaymentDo> tiktokOrderPaymentDos = tiktokOrderPaymentDao.selectList(new LambdaQueryWrapper<TiktokOrderPaymentDo>().eq(TiktokOrderPaymentDo::getOrderId, id));
            if (!tiktokOrderPaymentDos.isEmpty()) {
                orderVO.setPayment(tiktokOrderPaymentDos.get(0));
            }
            resList.add(orderVO);
        }
        return resList;
    }


    private LambdaQueryWrapper<TiktokOrderDo> queryBuild(OrderTiktokQueryBo bo) {
        LambdaQueryWrapper<TiktokOrderDo> lqw = new LambdaQueryWrapper<>();
        String status = bo.getStatus();
        if (StringUtils.isNotBlank(status)) {
            lqw.eq(TiktokOrderDo::getStatus, status);
        }
        if (StringUtils.isNotBlank(bo.getShopId())) {
            lqw.eq(TiktokOrderDo::getShopId, bo.getShopId());
        }
        if (StringUtils.isNotBlank(bo.getOrderId())) {
            lqw.eq(TiktokOrderDo::getOrderId, bo.getOrderId());
        }
        lqw.eq(TiktokOrderDo::getCompanyId, bo.getCompanyId());

        //是否转发货加入查询条件
        lqw.eq(Objects.nonNull(bo.getIsSendOut()), TiktokOrderDo::getIsSendOut, bo.getIsSendOut());
        return lqw;
    }

    /**
     * 将日期字符串转换为时间戳（毫秒）
     *
     * @param dateStr 日期字符串，格式为 "yyyy-MM-dd"
     * @return 时间戳（毫秒）
     */
    private Long convertToTimestamp(String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        try {
            LocalDateTime localDateTime = LocalDateTime.parse(dateStr, formatter);
            ZoneId zoneId = ZoneId.of("UTC"); // 明确指定时区，避免歧义
            return localDateTime.atZone(zoneId).toInstant().toEpochMilli();
        } catch (Exception e) {
            // 可以记录日志
            System.err.println("日期转换失败：" + dateStr + "，错误信息：" + e.getMessage());
            return null;
        }
    }

    private static GetOrderListRequestBody getGetOrderListRequestBody(Long startTimestamp, Long endTimestamp) {
        GetOrderListRequestBody getOrderListRequestBody = new GetOrderListRequestBody();
          /*  getOrderListRequestBody.setOrderStatus("UNPAID");
            getOrderListRequestBody.setCreateTimeGe(1623812664L);
            getOrderListRequestBody.setCreateTimeLt(1623812664L);*/
        getOrderListRequestBody.setUpdateTimeGe(startTimestamp);
        getOrderListRequestBody.setUpdateTimeLt(endTimestamp);
            /*getOrderListRequestBody.setShippingType("TIKTOK");
            getOrderListRequestBody.setBuyerUserId("7213489962827123654");
            getOrderListRequestBody.setIsBuyerRequestCancel(false);*/
/*        List<String> getOrderListRequestBodyWarehouseIdsList = new ArrayList<>(Arrays.asList("7000714532876273888","7000714532876273666"));
        getOrderListRequestBody.setWarehouseIds(getOrderListRequestBodyWarehouseIdsList);*/
        return getOrderListRequestBody;
    }

/*
    @Transactional(rollbackFor = Exception.class)
    @Override
    public  List<GetOrderListResponseDataOrders>  getOrder(String accessToken, String shopCipher, Integer shopId, String startDate, String endDate, Long companyId) throws Exception {
        Long startTimestamp = convertToTimestamp(startDate) / 1000;
        Long endTimestamp = convertToTimestamp(endDate) / 1000;

        CustomApiClient defaultClient = new CustomApiClient();
        defaultClient.setAppkey(appKey);
        defaultClient.setSecret(clientSecret);
        defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");

        OrderV202309Api apiInstance = new OrderV202309Api(defaultClient);
        GetOrderListRequestBody requestBody = getGetOrderListRequestBody(startTimestamp, endTimestamp);

        GetOrderListResponse result = apiInstance.order202309OrdersSearchPost(
                20, accessToken, "application/json", "ASC", "", "create_time", shopCipher, requestBody);

        List<GetOrderListResponseDataOrders> orders = result.getData().getOrders();
        System.out.println(result);
        System.out.println("accessToken:");
        System.out.println(accessToken);
        System.out.println("shopCipher:");
        System.out.println(shopCipher);
        System.out.println("shopId");
        System.out.println(shopId);

 //       handleAndSyncOrders(orders, shopId, companyId);

        return orders;
    }
*/

    @Transactional(rollbackFor = Exception.class)
    @Override
    public  List<GetOrderListResponseDataOrders> getOrder(String accessToken, String shopCipher, Long shopId, String startDate, String endDate, Long companyId) throws Exception {
        Long startTimestamp = convertToTimestamp(startDate) / 1000;
        Long endTimestamp = convertToTimestamp(endDate) / 1000;

        CustomApiClient defaultClient = new CustomApiClient();
        defaultClient.setAppkey(appKey);
        defaultClient.setSecret(clientSecret);
        defaultClient.setBasePath("https://open-api.tiktokglobalshop.com");

        OrderV202309Api apiInstance = new OrderV202309Api(defaultClient);
        GetOrderListRequestBody requestBody = getGetOrderListRequestBody(startTimestamp, endTimestamp);

        int pageSize = 20; // 每页最大支持数量（TikTok API 中为 20）
        String nextPageToken = null;
        List<GetOrderListResponseDataOrders> allOrders = new ArrayList<>();

        do {
            GetOrderListResponse result = apiInstance.order202309OrdersSearchPost(
                    pageSize,
                    accessToken,
                    "application/json",
                    "ASC",
                    nextPageToken, // 使用上一页的 nextPageToken 获取下一页
                    "create_time",
                    shopCipher,
                    requestBody
            );


            List<GetOrderListResponseDataOrders> orders = result.getData().getOrders();
            if (orders == null || orders.isEmpty()) {
                break;
            }

            allOrders.addAll(orders);
            nextPageToken = result.getData().getNextPageToken(); // 获取下一页 token

        } while (nextPageToken != null && !nextPageToken.isEmpty());

        tiktokService.handleAndSyncOrders(allOrders, shopId, companyId);

        return allOrders;
    }

    private void handleDistrictInfo(List<GetOrderListResponseDataOrdersRecipientAddressDistrictInfo> districtInfo, TiktokOrderDo tiktokOrderDo) {
        // 按索引设置值
        for (int i = 0; i < Math.min(districtInfo.size(), 5); i++) {
            GetOrderListResponseDataOrdersRecipientAddressDistrictInfo info = districtInfo.get(i);
            switch (i) {
                case 0:
                    tiktokOrderDo.setDistrictInfoAddressLevel0(info.getAddressLevel());
                    tiktokOrderDo.setDistrictInfoAddressLevelName0(info.getAddressLevelName());
                    tiktokOrderDo.setDistrictInfoAddressName0(info.getAddressName());
                    break;
                case 1:
                    tiktokOrderDo.setDistrictInfoAddressLevel1(info.getAddressLevel());
                    tiktokOrderDo.setDistrictInfoAddressLevelName1(info.getAddressLevelName());
                    tiktokOrderDo.setDistrictInfoAddressName1(info.getAddressName());
                    break;
                case 2:
                    tiktokOrderDo.setDistrictInfoAddressLevel2(info.getAddressLevel());
                    tiktokOrderDo.setDistrictInfoAddressLevelName2(info.getAddressLevelName());
                    tiktokOrderDo.setDistrictInfoAddressName2(info.getAddressName());
                    break;
                case 3:
                    tiktokOrderDo.setDistrictInfoAddressLevel3(info.getAddressLevel());
                    tiktokOrderDo.setDistrictInfoAddressLevelName3(info.getAddressLevelName());
                    tiktokOrderDo.setDistrictInfoAddressName3(info.getAddressName());
                    break;
                case 4:
                    tiktokOrderDo.setDistrictInfoAddressLevel4(info.getAddressLevel());
                    tiktokOrderDo.setDistrictInfoAddressLevelName4(info.getAddressLevelName());
                    tiktokOrderDo.setDistrictInfoAddressName4(info.getAddressName());
                    break;
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void handleAndSyncOrders(List<GetOrderListResponseDataOrders> orders, Long shopId, Long companyId) {
        if (orders == null || orders.isEmpty()) return;
        log.info("开始同步 TikTok 订单，共 {} 条", orders.size());
        Set<String> remoteOrderIds = orders.stream()
                .map(GetOrderListResponseDataOrders::getId)
                .collect(Collectors.toSet());
//本地是否存在拉取的订单id相同的
        List<TiktokOrderDo> existingOrders = tiktokOrderDao.selectList(new LambdaQueryWrapper<TiktokOrderDo>().in(TiktokOrderDo::getOrderId, remoteOrderIds));
        Map<String, TiktokOrderDo> existingOrderMap = existingOrders.stream()
                .collect(Collectors.toMap(TiktokOrderDo::getOrderId, o -> o));

        List<TiktokOrderDo> toInsertOrders = new ArrayList<>();
        List<TiktokOrderDo> toUpdateOrders = new ArrayList<>();

        List<TiktokOrderPaymentDo> toInsertPayments = new ArrayList<>();
        List<TiktokOrderPaymentDo> toUpdatePayments = new ArrayList<>();

        List<TiktokOrderPackageDo> toInsertPackages = new ArrayList<>();
        List<TiktokOrderPackageDo> toUpdatePackages = new ArrayList<>();
        Set<String> toDeletePackagesOrderIds = new HashSet<>();

        List<TiktokOrderLineItemDo> toInsertLineItems = new ArrayList<>();
        List<TiktokOrderLineItemDo> toUpdateLineItems = new ArrayList<>();
        Set<String> toDeleteLineItemsOrderIds = new HashSet<>();

        for (GetOrderListResponseDataOrders order : orders) {
            String orderId = order.getId();
            TiktokOrderDo tiktokOrderDo = new TiktokOrderDo();
            TiktokOrderPaymentDo tiktokOrderPaymentDo = new TiktokOrderPaymentDo();
            TiktokOrderDo existingOrder = existingOrderMap.get(orderId);
            if (existingOrder == null ){
                //处理要插入的订单信息(包含地址信息)
                processInsertOrders(shopId, companyId, order, tiktokOrderDo, toInsertOrders);
                //处理要插入的支付信息
                processInsertPayments(order, tiktokOrderPaymentDo, toInsertPayments);
                //处理要插入的商品信息
                processInsertLineItems(order,toInsertLineItems);
                //处理要插入的包裹信息
                processInsertPackages(order, toInsertPackages);
            }
            else if(isOrderChanged(existingOrder, order)) {
                //处理要更新的订单信息(包含地址信息)
                processUpdateOrders(shopId, companyId, order, tiktokOrderDo, toUpdateOrders);
                //处理要更新的支付信息
                processUpdatePayments(order, tiktokOrderPaymentDo, toUpdatePayments);
                //处理要更新的商品信息
                processUpdateItems(order, toDeleteLineItemsOrderIds, orderId, toInsertLineItems);
                //处理要更新的包裹信息
                processUpdatePackages(order, toDeletePackagesOrderIds, orderId, toInsertPackages);

            }
        }
        batchInsertOrUpdateLineItems(toInsertLineItems, toDeleteLineItemsOrderIds);
        batchInsertOrUpdatePackages(toInsertPackages, toDeletePackagesOrderIds);
        batchInsertOrUpdateOrders(toInsertOrders, toUpdateOrders);
        batchInsertOrUpdatePayments(toInsertPayments, toUpdatePayments);
        log.error("订单同步完成：新增 {} 条，更新{} 条", toInsertOrders.size(), toUpdateOrders.size());
    }

    private void processUpdatePackages(GetOrderListResponseDataOrders order, Set<String> toDeletePackagesOrderIds, String orderId, List<TiktokOrderPackageDo> toInsertPackages) {
        toDeletePackagesOrderIds.add(orderId);
        processInsertPackages(order, toInsertPackages);
    }

    private void processUpdateItems(GetOrderListResponseDataOrders order, Set<String> toDeleteLineItemsOrderIds, String orderId, List<TiktokOrderLineItemDo> toInsertLineItems) {
        toDeleteLineItemsOrderIds.add(orderId);
        processInsertLineItems(order, toInsertLineItems);
    }

    /**
     * 处理包裹信息：删除旧数据，插入新数据
     */
/*    private void processUpdatePackages(GetOrderListResponseDataOrders order, List<TiktokOrderPackageDo> toInsertPackages) {
        String orderId = order.getId();

        // 1. 删除该订单原有所有包裹信息
        tiktokOrderPackageDao.delete(new LambdaQueryWrapper<TiktokOrderPackageDo>()
                .eq(TiktokOrderPackageDo::getOrderId, orderId));

        // 2. 插入新的包裹信息
        List<GetOrderListResponseDataOrdersPackages> packages = order.getPackages();
        if (!CollectionUtils.isEmpty(packages)) {
            for (GetOrderListResponseDataOrdersPackages remotePackage : packages) {
                TiktokOrderPackageDo localPackage = new TiktokOrderPackageDo();
                localPackage.setOrderId(orderId);
                localPackage.setPackageId(remotePackage.getId());

                toInsertPackages.add(localPackage);
            }
        }
    }*/


/*    private  void processUpdateOrderItems(GetOrderListResponseDataOrders order, List<String> toDeleteLineItemsOrderIds) {


        //将lineItems中的数据进行分组，根据sku_id进行分组将skuid和其数量收集起来
        Map<String, List<GetOrderListResponseDataOrdersLineItems>> skuCountMap = lineItems.stream().collect(Collectors.groupingBy(GetOrderListResponseDataOrdersLineItems::getSkuId));

        for (GetOrderListResponseDataOrdersLineItems lineItem : lineItems) {

            TiktokOrderLineItemDo baseLineItem = new TiktokOrderLineItemDo();
            BeanUtils.copyProperties(lineItem,baseLineItem );
            baseLineItem.setOrderId(order.getId());
            baseLineItem.setSkuCount(skuCountMap.get(lineItem.getSkuId()).size());

            List<GetOrderListResponseDataOrdersLineItemsCombinedListingSkus> combinedListingSkus = lineItem.getCombinedListingSkus();
            if(combinedListingSkus.size()>0)
            {
                for (GetOrderListResponseDataOrdersLineItemsCombinedListingSkus listingSkus : combinedListingSkus) {
                    //  新建一个新对象，避免引用污染
                    TiktokOrderLineItemDo newLineItem = new TiktokOrderLineItemDo();
                    BeanUtils.copyProperties( baseLineItem,newLineItem); // 复制基础属性
                    newLineItem.setOrderId(order.getId());

                    Integer skuCount = listingSkus.getSkuCount();
                    String skuId = listingSkus.getSkuId();
                    String productId = listingSkus.getProductId();
                    String sellerSku = listingSkus.getSellerSku();

                    newLineItem.setSkuId(skuId);
                    newLineItem.setCombinedListingSkusProductId(productId);
                    newLineItem.setCombinedListingSkusSkuId(skuId);
                    newLineItem.setCombinedListingSkusSellerSku(sellerSku);
                    newLineItem.setSkuCount(skuCount);
                    toUpdateLineItems.add(newLineItem);
                }
            }else{
                toUpdateLineItems.add(baseLineItem);
            }
        }
    }*/
    private void processUpdatePayments(GetOrderListResponseDataOrders order, TiktokOrderPaymentDo tiktokOrderPaymentDo, List<TiktokOrderPaymentDo> toUpdatePayments) {
        // 更新支付信息
        GetOrderListResponseDataOrdersPayment payment = order.getPayment();
        BeanUtils.copyProperties(payment, tiktokOrderPaymentDo);
        tiktokOrderPaymentDo.setOrderId(order.getId());
        toUpdatePayments.add(tiktokOrderPaymentDo);
    }

    private void processUpdateOrders(Long shopId, Long companyId, GetOrderListResponseDataOrders order, TiktokOrderDo tiktokOrderDo, List<TiktokOrderDo> toUpdateOrders) {
        // 存在：用远程数据更新本地对象
        BeanUtils.copyProperties(order, tiktokOrderDo);
        //更新地址信息
        GetOrderListResponseDataOrdersRecipientAddress recipientAddress = order.getRecipientAddress();
        List<GetOrderListResponseDataOrdersRecipientAddressDistrictInfo> districtInfo = recipientAddress.getDistrictInfo();
        // 将远程地址信息复制到本地对象
        BeanUtils.copyProperties(recipientAddress, tiktokOrderDo);
        if ((districtInfo.size() > 0)) {
            //处理districtinfo
            handleDistrictInfo(districtInfo, tiktokOrderDo);
        }
        tiktokOrderDo.setShopId(shopId);
        tiktokOrderDo.setCompanyId(companyId);
        tiktokOrderDo.setOrderId(order.getId());
        toUpdateOrders.add(tiktokOrderDo);// 使用合并后的新数据进行更新
    }

    private void processInsertOrders(Long shopId, Long companyId, GetOrderListResponseDataOrders order, TiktokOrderDo tiktokOrderDo, List<TiktokOrderDo> toInsertOrders) {
        BeanUtils.copyProperties(order, tiktokOrderDo);

        //新增地址信息(在订单主表中)
        GetOrderListResponseDataOrdersRecipientAddress recipientAddress = order.getRecipientAddress();
        List<GetOrderListResponseDataOrdersRecipientAddressDistrictInfo> districtInfo = recipientAddress.getDistrictInfo();
        BeanUtils.copyProperties(recipientAddress, tiktokOrderDo);

        if ((districtInfo.size() > 0)) {
            //处理districtinfo
            handleDistrictInfo(districtInfo, tiktokOrderDo);
        }
        tiktokOrderDo.setShopId(shopId);
        tiktokOrderDo.setCompanyId(companyId);
        tiktokOrderDo.setOrderId(order.getId());
        //默认都是未发货
        tiktokOrderDo.setIsSendOut(0);
        //默认都是未删除
        tiktokOrderDo.setIsDeleted(0);
        toInsertOrders.add(tiktokOrderDo);
    }

    private void processInsertPayments(GetOrderListResponseDataOrders order, TiktokOrderPaymentDo tiktokOrderPaymentDo, List<TiktokOrderPaymentDo> toInsertPayments) {
        GetOrderListResponseDataOrdersPayment payment = order.getPayment();
        BeanUtils.copyProperties(payment, tiktokOrderPaymentDo);
        tiktokOrderPaymentDo.setOrderId(order.getId());
        toInsertPayments.add(tiktokOrderPaymentDo);
    }

    private void processInsertPackages(GetOrderListResponseDataOrders order, List<TiktokOrderPackageDo> toInsertPackages) {
        List<GetOrderListResponseDataOrdersPackages> packages = order.getPackages();
        for (GetOrderListResponseDataOrdersPackages aPackage : packages) {
            TiktokOrderPackageDo tiktokOrderPackageDo = new TiktokOrderPackageDo();
            tiktokOrderPackageDo.setPackageId(aPackage.getId());
            tiktokOrderPackageDo.setOrderId(order.getId());
            toInsertPackages.add(tiktokOrderPackageDo);
        }
    }

    private void processInsertLineItems(GetOrderListResponseDataOrders order, List<TiktokOrderLineItemDo> toInsertLineItems) {
        // 新增商品信息
        List<GetOrderListResponseDataOrdersLineItems> lineItems = order.getLineItems();
        if (lineItems == null) {
            return;
        }
        //将lineItems中的数据进行分组，根据sku_id进行分组将skuid和其数量收集起来
        Map<String, List<GetOrderListResponseDataOrdersLineItems>> skuCountMap = lineItems.stream().collect(Collectors.groupingBy(GetOrderListResponseDataOrdersLineItems::getSkuId));
//过滤相同的lineItems就是说收集的每一个都是不一样的
        // 提取每个 skuId 分组中的第一个元素，即保留唯一一份
        List<GetOrderListResponseDataOrdersLineItems> uniqueLineItems = skuCountMap.values().stream()
                .filter(list -> !list.isEmpty()) // 非空校验
                .map(list -> list.get(0))        // 每个分组取第一个
                .collect(Collectors.toList());


        for (GetOrderListResponseDataOrdersLineItems lineItem : uniqueLineItems) {
            TiktokOrderLineItemDo baseLineItem = new TiktokOrderLineItemDo();
            BeanUtils.copyProperties(lineItem, baseLineItem);
            baseLineItem.setSkuCount(skuCountMap.get(lineItem.getSkuId()).size());
            baseLineItem.setOrderId(order.getId());

            List<GetOrderListResponseDataOrdersLineItemsCombinedListingSkus> combinedListingSkus = lineItem.getCombinedListingSkus();
            if (combinedListingSkus != null && !combinedListingSkus.isEmpty()) {
                for (GetOrderListResponseDataOrdersLineItemsCombinedListingSkus listingSkus : combinedListingSkus) {
                    TiktokOrderLineItemDo newLineItem = new TiktokOrderLineItemDo();
                    BeanUtils.copyProperties(baseLineItem, newLineItem); // 复制基础字段
                    newLineItem.setOrderId(order.getId());
                    Integer skuCount = listingSkus.getSkuCount();
                    String skuId = listingSkus.getSkuId();
                    String productId = listingSkus.getProductId();
                    String sellerSku = listingSkus.getSellerSku();

                    newLineItem.setSkuId(skuId);
                    newLineItem.setCombinedListingSkusProductId(productId);
                    newLineItem.setCombinedListingSkusSkuId(skuId);
                    newLineItem.setCombinedListingSkusSellerSku(sellerSku);
                    newLineItem.setSkuCount(skuCount);

                    toInsertLineItems.add(newLineItem);
                }
            } else {
                toInsertLineItems.add(baseLineItem);
            }
        }
    }


    //todo 后期如果需要修改本地数据记得提前手动设置更新时间
    private boolean isOrderChanged(TiktokOrderDo existing, GetOrderListResponseDataOrders incoming) {
        Long remoteUpdateTime = incoming.getUpdateTime();
        Long localUpdateTime = existing.getUpdateTime();

        if (remoteUpdateTime == null || localUpdateTime == null) {
            return remoteUpdateTime != null || localUpdateTime != null;
        }

        if (remoteUpdateTime > localUpdateTime) {
            log.error("订单 {} updateTime 更新（{} -> {}），将执行更新",
                    incoming.getId(), localUpdateTime, remoteUpdateTime);
            return true;
        } else if (remoteUpdateTime < localUpdateTime) {
            log.error("订单 {} 远程 updateTime({}) < 本地 updateTime({})，可能为异常数据，请检查",
                    incoming.getId(), remoteUpdateTime, localUpdateTime);
            // 可选：调用监控系统报警
            return false; // 不更新
        } else {
            log.error("订单 {} updateTime 未变，跳过更新", incoming.getId());
            return false;
        }
    }


    private void batchInsertOrUpdateOrders(List<TiktokOrderDo> toInsertOrders, List<TiktokOrderDo> toUpdateOrders) {
        // 插入
        if (!toInsertOrders.isEmpty()) {
            Lists.partition(toInsertOrders, BATCH_SIZE).forEach(tiktokOrderDao::insertBatch);
        }

        // 更新
        if (!toUpdateOrders.isEmpty()) {
            Lists.partition(toUpdateOrders, BATCH_SIZE).forEach(tiktokOrderDao::updateBatchByOrderId);
        }
    }

    private void batchInsertOrUpdatePackages(List<TiktokOrderPackageDo> toInsertPackages, Set<String> toDeletePackageOrderIds) {
        //修改=先删后插
        if (!toDeletePackageOrderIds.isEmpty()) {
            tiktokOrderPackageDao.delete(new LambdaQueryWrapper<TiktokOrderPackageDo>().in(TiktokOrderPackageDo::getOrderId, toDeletePackageOrderIds));
        }
        if (!toInsertPackages.isEmpty()) {
            Lists.partition(toInsertPackages, BATCH_SIZE).forEach(tiktokOrderPackageDao::insertBatch);
        }

    }

    private void batchInsertOrUpdateLineItems(List<TiktokOrderLineItemDo> toInsertLineItems, Set<String> toDeleteLineItemsOrderIds) {
        //修改=先删后插
        if (!toDeleteLineItemsOrderIds.isEmpty()) {
            tiktokOrderLineItemDao.delete(new LambdaQueryWrapper<TiktokOrderLineItemDo>().in(TiktokOrderLineItemDo::getOrderId, toDeleteLineItemsOrderIds));
        }
        if (!toInsertLineItems.isEmpty()) {
            Lists.partition(toInsertLineItems, BATCH_SIZE).forEach(tiktokOrderLineItemDao::insertBatch);
        }

    }

    private void batchInsertOrUpdatePayments(List<TiktokOrderPaymentDo> toInsertPayments, List<TiktokOrderPaymentDo> toUpdatePayments) {
        if (!toInsertPayments.isEmpty()) {
            Lists.partition(toInsertPayments, BATCH_SIZE).forEach(tiktokOrderPaymentDao::insertBatch);
        }

        if (!toUpdatePayments.isEmpty()) {
            Lists.partition(toUpdatePayments, BATCH_SIZE).forEach(tiktokOrderPaymentDao::updateBatchById);
        }
    }























    /*private void handleOrder(List<GetOrderListResponseDataOrders> orders, Integer shopId) {

        // 收集远程订单ID
        Set<String> remoteOrderIds = orders.stream()
                .map(GetOrderListResponseDataOrders::getId)
                .collect(Collectors.toSet());

        // 查询本地所有订单ID
        List<TiktokOrderDo> existingOrders = tiktokOrderDao.selectList(null);
        Map<String, TiktokOrderDo> existingOrderMap = existingOrders.stream()
                .collect(Collectors.toMap(TiktokOrderDo::getId, o -> o));

        List<TiktokOrderDo> toInsertOrders = new ArrayList<>();
        List<TiktokOrderDo> toUpdateOrders = new ArrayList<>();

        List<TiktokOrderPaymentDo> toInsertPayments = new ArrayList<>();
        List<TiktokOrderPaymentDo> toUpdatePayments = new ArrayList<>();

        List<TiktokOrderPackageDo> toInsertPackages = new ArrayList<>();
        List<TiktokOrderLineItemDo> toInsertLineItems = new ArrayList<>();
        for (GetOrderListResponseDataOrders order : orders) {
            String orderId = order.getId();

            TiktokOrderDo tiktokOrderDo = new TiktokOrderDo();
            BeanUtils.copyProperties(order, tiktokOrderDo);
            tiktokOrderDo.setShopId(shopId);

            if (existingOrderMap.containsKey(orderId)) {
                // 存在则更新主表
                TiktokOrderDo existingOrder = existingOrderMap.get(orderId);
                BeanUtils.copyProperties(existingOrder, tiktokOrderDo); // 可根据字段判断是否需要更新
                toUpdateOrders.add(existingOrder);
            } else {
                // 不存在则插入主表
                toInsertOrders.add(tiktokOrderDo);
            }

            // 支付信息
            GetOrderListResponseDataOrdersPayment payment = order.getPayment();
            if (payment != null) {
                TiktokOrderPaymentDo paymentDo = new TiktokOrderPaymentDo();
                BeanUtils.copyProperties(paymentDo, payment);
                paymentDo.setOrderId(orderId);

                if (existingOrderMap.containsKey(orderId)) {
                    toUpdatePayments.add(paymentDo);
                } else {
                    toInsertPayments.add(paymentDo);
                }
            }

            // 地址信息
            GetOrderListResponseDataOrdersRecipientAddress recipientAddress = order.getRecipientAddress();
            // 包裹信息
            for (GetOrderListResponseDataOrdersPackages aPackage : order.getPackages()) {
                TiktokOrderPackageDo packageDo = new TiktokOrderPackageDo();
                packageDo.setOrderId(orderId);
                packageDo.setPackageId(aPackage.getId());
                toInsertPackages.add(packageDo);
            }

            // 商品明细
            for (GetOrderListResponseDataOrdersLineItems lineItem : order.getLineItems()) {
                TiktokOrderLineItemDo itemDo = new TiktokOrderLineItemDo();
                BeanUtils.copyProperties(itemDo, lineItem);
                itemDo.setOrderId(orderId);
                toInsertLineItems.add(itemDo);
            }
        }
    }*/


}
